package com.example.BlockChain.controller;

import com.example.BlockChain.dao.TChainDataDao;
import com.example.BlockChain.entity.*;

import com.example.BlockChain.service.BlockService;
import com.example.BlockChain.service.TimingService;
import com.example.BlockChain.service.UserService;
import com.example.BlockChain.utils.DateUtils;
import com.example.BlockChain.utils.EthUtils;
import com.example.BlockChain.utils.PendingUtils;
import com.example.BlockChain.utils.SnowflakeIdUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.mybatis.logging.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.ECKeyPair;
import org.web3j.crypto.Keys;
import org.web3j.crypto.Sign;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import org.slf4j.Logger;
import java.util.stream.Collectors;


@RestController
public class ChainController {


    @Value("${node.ip}") // 动态读取配置文件中的区块链节点 IP 地址
    private String ip;

    @Resource
    private BlockService blockService;

    @Resource
    private UserService userService;

    @Resource
    private TimingService timingService;

    @Resource // 注入链上数据数据库操作对象
    private TChainDataDao chainDataDao;

    @Resource // 注入 RestTemplate，用于发送 HTTP 请求
    private RestTemplate restTemplate;

    /**
     * 上传消费者订单
     *
     * @return ResponseEntity
     */
    @RequestMapping(value = "/consumerOrder")
    public ResponseEntity<JSONObject> consumerOrder(@RequestBody Map<String, Object> formData) throws Exception {
        // 创建返回的JSON对象
        JSONObject jo = new JSONObject();

        //获取当前用户id，用于查找私钥
        Object userId = formData.get("userid"); // 根据 key 取值
        int userid = Integer.parseInt(userId.toString());
        TUser Cuser = userService.getUser(userid);

        String jsonContent = new ObjectMapper().writeValueAsString(formData);//将formData转化成String类型

        jo.setO(jsonContent);

        // 使用雪花算法生成唯一溯源码
        SnowflakeIdUtils idWorker = new SnowflakeIdUtils(3, 1);
        String code = String.valueOf(idWorker.nextId());


        // 构建链上数据对象
        TChainData chainData = new TChainData();
        chainData.setCode(code);//设置溯源码
        chainData.setFromAddress(Cuser.getAddress()); // 示例数据
        chainData.setToAddress("system");
        chainData.setContent(jsonContent); // 设置 JSON 字符串到 content 字段
        chainData.setOperationType(1);
        chainData.setBlockIndex(null);
        chainData.setCreateTime(LocalDateTime.now().toString());
        chainData.setChainStatus("0");

        //将得到的溯源码更新在Timing表
        Timing newtiming = new Timing();
        newtiming.setOrderId(code);
        timingService.setNewTiming(newtiming);

        //将上链数据转换为 JSON 格式
        Gson gson = new GsonBuilder()
                .disableHtmlEscaping() // 禁用 HTML 转义
                .create();
        String jsonStr = gson.toJson(chainData);

        // 私钥解析，用于数据签名
        BigInteger pri = new BigInteger(Cuser.getPrivateKey(), 16);

        // 构建交易对象
        TradeObject tradeObject = new TradeObject();
        tradeObject.setFrom(Cuser.getAddress()); // 数据发送方地址
        tradeObject.setTo("system"); // 数据接收方地址
        tradeObject.setType("1"); // 数据类型，1 表示上链数据
        tradeObject.setContent(jsonStr); // 上链的具体内容
        tradeObject.setJsoncreatetime(DateUtils.getTime()); // JSON 数据创建时间
        tradeObject.setObjToString(tradeObject.toString()); // 对象的字符串表示

        jo.setO(tradeObject);
        // 对交易对象进行签名
        Sign.SignatureData signatureData = EthUtils.signMessage(tradeObject.toString(), pri);
        String sign = EthUtils.getSignStr(signatureData); // 获取签名字符串
        tradeObject.setSign(sign); // 设置签名

        // 生成交易唯一哈希值
        String hashNo = PendingUtils.genTradeNo(tradeObject);
        chainData.setHashNo(hashNo); // 设置链上数据的哈希值

        // 保存上链数据到数据库
        chainDataDao.save(chainData);
        jo.setO(chainData);

         //发送交易到区块链节点：调试的时候先别把这个取消注释，不然通不过
        String url = "http://" + ip + ":8001/data/trade"; // 节点接口地址
        try {
            restTemplate.postForEntity(url, tradeObject, TradeObject.class);
        } catch (Exception e) {
            jo.setCode("500");
            jo.setMsg("请求区块链节点超时或失败：" + e.getMessage());
            return new ResponseEntity<>(jo, HttpStatus.INTERNAL_SERVER_ERROR);
        }


        jo.setCode("200");
        jo.setMsg("订单更新成功！");
        return new ResponseEntity<JSONObject>(jo, HttpStatus.OK);
    }

    /**
     * 商家完成订单接口
     *
     * @return ResponseEntity
     */
    @RequestMapping(value = "/merchantOkOrder", method = RequestMethod.POST)
    public ResponseEntity<JSONObject> merchantOkOrder(@RequestBody Map<String, Object> formData) throws Exception {
        // 创建返回的 JSON 对象
        JSONObject jo = new JSONObject();

        // 获取商家用户 ID，用于查找私钥
        Object userId = formData.get("merchantId");
        int merchantId = Integer.parseInt(userId.toString());
        TUser merchant = userService.getUserById(merchantId);

        if (merchant == null) {
            jo.setCode("404");
            jo.setMsg("商家信息不存在！");
            return new ResponseEntity<>(jo, HttpStatus.NOT_FOUND);
        }

        // 更新订单完成时间
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String okTime = now.format(formatter); // 格式化为字符串

        // 获取订单 ID
        String orderId = String.valueOf(formData.get("orderId"));
        //查询商家接单时间
        String acceptTime = timingService.selectTiming2(orderId);

        if (acceptTime == null) {
            jo.setCode("400");
            jo.setMsg("订单时间数据不存在！");
            jo.setO(acceptTime);
            return new ResponseEntity<>(jo, HttpStatus.BAD_REQUEST);
        }

        // 构建订单时间信息
        Map<String, String> times = new HashMap<>();
        times.put("merchantAcceptTime", acceptTime);
        times.put("merchantCompleteTime", okTime);

        // 将时间信息转换为 JSON 字符串
        ObjectMapper objectMapper = new ObjectMapper();
        String resultJson = objectMapper.writeValueAsString(times);

        // 构建链上数据对象
        TChainData chainData = new TChainData();
        chainData.setCode(orderId);
        chainData.setFromAddress(merchant.getAddress());
        chainData.setToAddress("system");
        chainData.setContent(resultJson);
        chainData.setOperationType(3); // 设置为商家完成订单操作
        chainData.setBlockIndex(null);
        chainData.setCreateTime(LocalDateTime.now().toString());
        chainData.setChainStatus("0");

        // 修改 operation_type=3，用于前端检测按钮状态
        blockService.updateOperationType3(orderId, 3);

        // 将链上数据转换为 JSON 格式
        Gson gson = new GsonBuilder()
                .disableHtmlEscaping()
                .create();
        String jsonStr = gson.toJson(chainData);

        // 商家私钥解析，用于数据签名
        BigInteger pri = new BigInteger(merchant.getPrivateKey(), 16);

        // 构建交易对象
        TradeObject tradeObject = new TradeObject();
        tradeObject.setFrom(merchant.getAddress());
        tradeObject.setTo("system");
        tradeObject.setType("1");
        tradeObject.setContent(jsonStr);
        tradeObject.setJsoncreatetime(DateUtils.getTime());
        tradeObject.setObjToString(tradeObject.toString());

        // 对交易对象进行签名
        Sign.SignatureData signatureData = EthUtils.signMessage(tradeObject.toString(), pri);
        String sign = EthUtils.getSignStr(signatureData);
        tradeObject.setSign(sign);

        // 生成交易唯一哈希值
        String hashNo = PendingUtils.genTradeNo(tradeObject);
        chainData.setHashNo(hashNo);

        // 保存链上数据到数据库
        chainDataDao.save(chainData);

        // 发送交易到区块链节点

        // 发送交易到区块链节点
        String url = "http://" + ip + ":8001/data/trade"; // 节点接口地址
        restTemplate.postForEntity(url, tradeObject, TradeObject.class); // POST 请求发送交易

        // 更新订单完成时间
        //timingService.updateCompleteTime3(orderId, okTime);
        blockService.updateOperationType3(orderId,3);

        // 返回成功信息
        jo.setCode("200");
        jo.setMsg("订单完成成功并已上链！");
        return new ResponseEntity<>(jo, HttpStatus.OK);
    }

    /**
     * 上传配送员订单
     *
     * @return ResponseEntity
     */
    @RequestMapping(value = "/deliveryOKOrder")
    public ResponseEntity<JSONObject> deliveryOKOrder(@RequestBody Map<String, Object> formData) throws Exception {
        // 创建返回的JSON对象
        JSONObject jo = new JSONObject();


        //获取当前用户id，用于查找私钥
        Object userId = formData.get("userid"); // 根据 key 取值
        int userid = Integer.parseInt(userId.toString());
        TUser Cuser = userService.getUser(userid);

        //更新订单完成时间
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String okTime = now.format(formatter);  // 格式化为字符串

        //取得订单时间数据
        String orderid = String.valueOf(formData.get("orderId"));//将Object对象转换成Sting类型的溯源码

        String acceptTime = timingService.selectTiming(orderid);

        Map<String, String> times = new HashMap<>();
        times.put("riderAcceptTime", acceptTime);
        times.put("riderCompleteTime", okTime);
        times.put("deliveryname", Cuser.getUsername());

        ObjectMapper objectMapper = new ObjectMapper();
        String resultJson = objectMapper.writeValueAsString(times);
        jo.setO(resultJson);

        // 构建链上数据对象
        TChainData chainData = new TChainData();
        chainData.setCode(orderid);//设置溯源码
        chainData.setFromAddress(Cuser.getAddress()); // 示例数据
        chainData.setToAddress("system");
        chainData.setContent(resultJson); // 设置 JSON 字符串到 content 字段
        chainData.setOperationType(5);//表示是配送员身份操作
        chainData.setBlockIndex(null);
        chainData.setCreateTime(LocalDateTime.now().toString());
        chainData.setChainStatus("0");

        //修改operation_type=5:用于前端检测按钮状态
        blockService.updateOperationType5(orderid);

        //将上链数据转换为 JSON 格式
        Gson gson = new GsonBuilder()
                .disableHtmlEscaping() // 禁用 HTML 转义
                .create();
        String jsonStr = gson.toJson(chainData);


        // 私钥解析，用于数据签名
        BigInteger pri = new BigInteger(Cuser.getPrivateKey(), 16);


        // 构建交易对象
        TradeObject tradeObject = new TradeObject();
        tradeObject.setFrom(Cuser.getAddress()); // 数据发送方地址
        tradeObject.setTo("system"); // 数据接收方地址
        tradeObject.setType("1"); // 数据类型，1 表示上链数据
        tradeObject.setContent(jsonStr); // 上链的具体内容
        tradeObject.setJsoncreatetime(DateUtils.getTime()); // JSON 数据创建时间
        tradeObject.setObjToString(tradeObject.toString()); // 对象的字符串表示

        jo.setO(tradeObject);
        // 对交易对象进行签名
        Sign.SignatureData signatureData = EthUtils.signMessage(tradeObject.toString(), pri);
        String sign = EthUtils.getSignStr(signatureData); // 获取签名字符串
        tradeObject.setSign(sign); // 设置签名

        // 生成交易唯一哈希值
        String hashNo = PendingUtils.genTradeNo(tradeObject);
        chainData.setHashNo(hashNo); // 设置链上数据的哈希值

        // 保存上链数据到数据库
        chainDataDao.save(chainData);
        jo.setO(chainData);

        //搜索三条溯源记录，生成最终订单
        List<TChainData> orderList = blockService.getThreeOrders(orderid);


        // 发送交易到区块链节点
        String url = "http://" + ip + ":8001/data/trade"; // 节点接口地址
        restTemplate.postForEntity(url, tradeObject, TradeObject.class); // POST 请求发送交易


        jo.setCode("200");
        jo.setMsg("订单更新成功！");
        return new ResponseEntity<JSONObject>(jo, HttpStatus.OK);
    }

    /**
     * 获取所有订单列表（用户界面）
     *
     * @return ResponseEntity 包装的JSON结果
     */
    @GetMapping(value = "/getConsumerorder")
    public ResponseEntity<JSONObject> getConsumerorder(@RequestParam int userid) {
        // 创建返回的JSON对象
        JSONObject response = new JSONObject();
        try {
            // 获取用户的钱包地址
            String address = userService.getAdress(userid);

            //获取订单数据（假设是 JSON 格式字符串列表）
            List<TChainData> orderList = blockService.getAllOrders(address);

            // 判断是否有订单
            if (orderList.isEmpty()) {
                response.setCode("404");
                response.setMsg("暂无商品信息");
                return new ResponseEntity<>(response, HttpStatus.OK);
            }
            // 将解析后的数据存入 JSON 响应对象
            response.setCode("200");
            response.setMsg("商品列表获取成功");
            response.setO(orderList);
            return new ResponseEntity<>(response, HttpStatus.OK);
        } catch (Exception e) {
            // 处理异常情况并返回错误信息
            response.setCode("500");
            response.setMsg("服务器内部错误: " + e.getMessage());
            return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 获取商家与配送员的订单列表（用户界面）
     *
     * @return ResponseEntity 包装的JSON结果
     */
    @GetMapping(value = "/getMerandDelOrders")
    public ResponseEntity<JSONObject> getMerandDelOrders(@RequestParam String code) {
        System.out.println("收到的 code 参数: " + code); // 打印接收到的 code
        // 创建返回的JSON对象
        JSONObject response = new JSONObject();
        try {
            // 获取用户的钱包地址

            //获取订单数据（假设是 JSON 格式字符串列表）
            List<TChainData> orderList = blockService.getMerandDelOrders(code);

            // 判断订单数量并进行保护性处理
            while (orderList.size() < 2) {
                orderList.add(TChainData.createDefault()); // 添加空占位数据 // 添加空对象占位，避免前端解析报错
            }

            // 将解析后的数据存入 JSON 响应对象
            response.setCode("200");
            response.setMsg("订单获取获取成功");
            response.setO(orderList);
            return new ResponseEntity<>(response, HttpStatus.OK);
        } catch (Exception e) {
            // 处理异常情况并返回错误信息
            response.setCode("500");
            response.setMsg("服务器内部错误: " + e.getMessage());
            return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    /**
     * 获取店铺的订单列表
     *
     * @param userid 店铺名称，不能为空
     * @param type 订单类型（如：新订单、历史订单等），默认为“all”
     * @return 返回一个包含订单信息的响应
     */
    @GetMapping(value = "/getStoreOrders")
    public ResponseEntity<String> getStoreOrders(
            @RequestParam int userid,  // 店铺名称
            @RequestParam(required = false, defaultValue = "all") String type) throws JsonProcessingException {  // 订单类型，默认为 "all"
        TUser user=userService.getUserById(userid);
        String storeName=user.getUsername();
        // 创建一个 ObjectMapper 实例，用于将 Java 对象转换为 JSON 字符串
        ObjectMapper mapper = new ObjectMapper();

        // 创建一个 Map 来构造响应数据
        Map<String, Object> response = new HashMap<>();

        try {
            // 检查店铺名称是否为空
            if (storeName == null || storeName.isEmpty()) {
                // 如果店铺名称为空，返回 400 错误和相应的提示消息
                response.put("code", "400");
                response.put("msg", "店铺名不能为空");
                response.put("data", null);
                return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                        .body(mapper.writeValueAsString(response));
            }
            response.put("storeName", storeName);

            // 调用 service 层方法，根据店铺名称和订单类型获取订单列表
            List<TChainData> orderList = blockService.getOrdersByTypeAndStore(storeName, type);

            // 如果订单列表为空，返回 404 状态码，表示没有订单
            if (orderList.isEmpty()) {
                response.put("code", "404");
                response.put("msg", "暂无订单信息");
                response.put("data", null);
                return ResponseEntity.status(HttpStatus.OK)
                        .body(mapper.writeValueAsString(response));
            }

            // 如果订单列表不为空，返回 200 状态码，表示获取成功
            response.put("code", "200");
            response.put("msg", "订单列表获取成功");
            response.put("data", orderList);

            // 返回成功的响应数据，200 OK
            return ResponseEntity.ok(mapper.writeValueAsString(response));

        } catch (Exception e) {
            // 记录错误日志，方便排查问题
            // 如果发生异常，返回 500 状态码，并包含错误信息
            response.put("code", "500");
            response.put("msg", "服务器内部错误: " + e.getMessage());
            response.put("data", null);

            // 返回服务器错误响应，500 Internal Server Error
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(mapper.writeValueAsString(response));
        }
    }

    /**
     * 获取配送员的订单列表
     *
     * @param type 订单类型（如：新订单、历史订单等），默认为“all”
     * @return 返回一个包含订单信息的响应
     */

    @GetMapping(value = "/getDeliveryorder")
    public ResponseEntity<String> getDeliveryorder(
            @RequestParam(required = false, defaultValue = "all") String type) throws JsonProcessingException {

        ObjectMapper mapper = new ObjectMapper(); // JSON 转换工具
        Map<String, Object> response = new HashMap<>(); // 构造响应数据

        try {
             //根据订单类型调用 Service 层获取订单数据
            List<TChainData> orderList = blockService.getDeliveryOrdersByType(type);
            response.put("data", orderList);
            // 检查订单列表是否为空
            if (orderList == null || orderList.isEmpty()) {
                response.put("code", "404");
                response.put("msg", "暂无订单信息");
                response.put("data", null);
                return ResponseEntity.status(HttpStatus.OK)
                        .body(mapper.writeValueAsString(response));
            }
             //如果订单列表不为空，返回成功响应
            response.put("code", "200");
            response.put("msg", "订单列表获取成功");
            response.put("data", orderList);
            return ResponseEntity.ok(mapper.writeValueAsString(response));
        } catch (IllegalArgumentException e) {
            // 捕获非法参数异常并返回 400 错误
            response.put("code", "400");
            response.put("msg", "非法参数: " + e.getMessage());
            response.put("data", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(mapper.writeValueAsString(response));
        } catch (Exception e) {
            // 捕获其他异常并返回 500 错误
            response.put("code", "500");
            response.put("msg", "服务器内部错误: " + e.getMessage());
            response.put("data", null);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(mapper.writeValueAsString(response));
        }
    }

    /**
     * 商家接单接口
     * @param formData 包含订单ID的请求体
     * @return 接单结果
     */
    @PostMapping("/merchantAcceptOrder")
    public ResponseEntity<String> merchantAcceptOrder(@RequestBody Map<String, Object> formData) {
        try {
            // 获取订单ID
            String orderId = (String) formData.get("orderId");

            // 检查订单ID是否有效
            if (orderId == null || orderId.trim().isEmpty()) {
                return ResponseEntity.badRequest().body("订单ID不能为空");
            }

            // 调用业务逻辑处理
            blockService.merchantAcceptOrder(orderId);

            // 返回成功消息
            return ResponseEntity.ok("商家接单成功");
        } catch (Exception e) {
            // 捕获异常并返回500状态
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("接单失败：" + e.getMessage());
        }
    }



}






